package com.linkdood.app.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.io.BaseEncoding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;

/**
 * 资源工具类
 * @author YunJ
 */
public class ResourceUtil {
    private static final Logger logger = LoggerFactory.getLogger(ResourceUtil.class);

    /**
     * 返回成功消息
     */
    public static Map<String, String> success() {
        Map<String, String> map = new HashMap<>(2);
        map.put("code", "0");
        map.put("msg", "success");
        return map;
    }

    /**
     * 获取返回给前端的错误信息
     */
    public static String getErrorMessage(String code) {
        String paramDesc = ResourceUtil.transformMessageByLocale(code);
        Map<String, Object> map = new HashMap<>(2);
        map.put("code", code);
        map.put("desc", paramDesc);

        ObjectMapper objectMapper = new ObjectMapper();
        String msg = "";
        try {
            msg = objectMapper.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            logger.error("getErrorMessage failed");
        }
        return msg;
    }

    public static String getErrorMessage(String code, String args) {
        Map<String, Object> map = new HashMap<>(3);
        map.put("code", code);

        String paramDesc = ResourceUtil.transformMessageByLocale(code);
        if (!StringUtils.isEmpty(args)) {
            paramDesc = paramDesc + " : " + args;
            map.put("args", TypeSafeUtil.parseStringList(args));
        }
        map.put("desc", paramDesc);

        ObjectMapper objectMapper = new ObjectMapper();
        String msg = "";
        try {
            msg = objectMapper.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            logger.error("getErrorMessage failed");
        }
        return msg;
    }

    /**
     * 将字符串改转国际化
     */
    public static String transformMessageByLocale(String param) {
        Locale locale = LocaleContextHolder.getLocale();
        if (locale == null) {
            locale = Locale.getDefault();
        }
        MessageSource messageSource = ResourceUtil.getMessageSource();
        return messageSource.getMessage(param, null, "", locale);
    }

    /**
     * 国际化
     */
    public static ReloadableResourceBundleMessageSource getMessageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setCacheSeconds(-1);
        messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name());
        messageSource.setBasenames("/i18n/messages");
        return messageSource;
    }

    /**
     * 密码加密
     */
    public static String encodePwd(String str) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        return bCryptPasswordEncoder.encode(str);
    }

    /**
     * 密码匹配
     */
    public static Boolean matchPwd(String password, String pwdEncode) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        return bCryptPasswordEncoder.matches(MD5Util.MD5Encode(password), pwdEncode);
    }

    /**
     * 随机生成一个字符与数字的字符串
     */
    public static String generatingRandomAlphanumericString(int targetStringLength) {
        // numeral '0'
        int leftLimit = 48;
        // letter 'z'
        int rightLimit = 122;
        Random random = new Random();

        return random.ints(leftLimit, rightLimit + 1)
                .filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97))
                .limit(targetStringLength)
                .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
                .toString();
    }

    /**
     * base64 解码
     */
    public static String base64Decode(String str) {
        BaseEncoding baseEncoding = BaseEncoding.base64();
        return new String(baseEncoding.decode(str));
    }

    public static String base64Encode(byte[] str) {
        BaseEncoding baseEncoding = BaseEncoding.base64();
        return baseEncoding.encode(str);
    }

    /**
     * 进行国际化处理
     */
    public static String getMessage(String msg) {
        Locale locale = LocaleContextHolder.getLocale();
        if (locale == null) {
            locale = Locale.getDefault();
        }
        MessageSource messageSource = getMessageSource();
        return messageSource.getMessage(msg, null, "", locale);
    }

    /**
     * 将一组数据固定分组，每组n个元素
     * @param source 要分组的数据源
     * @param n      每组n个元素
     * @param <T>
     * @return
     */
    public static <T> List<List<T>> fixedGrouping(Collection<T> source, int n) {
        if (null == source || source.size() == 0 || n <= 0) {
            return null;
        }
        List<T> sourceList = new ArrayList<>(source);
        List<List<T>> result = new ArrayList<>();
        int remainder = sourceList.size() % n;
        int size = (sourceList.size() / n);
        for (int i = 0; i < size; i++) {
            List<T> subset;
            subset = sourceList.subList(i * n, (i + 1) * n);
            result.add(subset);
        }
        if (remainder > 0) {
            List<T> subset;
            subset = sourceList.subList(size * n, size * n + remainder);
            result.add(subset);
        }
        return result;
    }
}
